﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data;

namespace ADOWrapper.ObjectResolver
{
    class TuplePopulator<T> : IObjectPopulator<T>
    {

        private static Func<IDataRecord, T> createTupleDelegate;
        static TuplePopulator()
        {

            Type[] genericArguments = typeof(T).GetGenericArguments();

            var recordValues = new Expression[genericArguments.Length];
            var parameter = Expression.Parameter(typeof(IDataRecord), "record");

            for (int i = 0; i < genericArguments.Length; i++)
            {
                var genericConverterMethod = SimpleConverter.GetConvertMethodInfo(genericArguments[i]);
                recordValues[i] = Expression.Call(genericConverterMethod, Expression.Call(parameter, "get_Item", null, Expression.Constant(i)));
            }

            var cci = typeof(T).GetConstructor(genericArguments);
            Expression<Func<IDataRecord, T>> ex = Expression.Lambda<Func<IDataRecord, T>>(Expression.New(cci, recordValues), parameter);
            
            createTupleDelegate = ex.Compile();
        }

        public T Populate(IDataRecord record)
        {            
            return createTupleDelegate(record);
        }
    }
}
